package JET.physics;

import JET.physics.bodies.SpringBody;
import JET.geom.Rect2d;
import JET.geom.Sec2d;
import JET.geom.Vec2d;
import JET.Constants;
import JET.physics.interfaces.SceneTreeNode;
import java.util.ArrayList;
import org.w3c.dom.*;


/**
 *
 * @author 057Ry
 */
public final class Wall implements Constants, SceneTreeNode
{
    static int id=0;
    
    public Mass m1,m2;
    Wall prev;
    Wall next; // sasiedzi sciany
    int mid;
    
    public Wall( Mass v1, Mass v2 )
    {
        this.m1 = v1;
        this.m2 = v2;
        mid = id++;
        prev = null;
        next = null;
    }

    public Wall(Element wallXMLElement, ArrayList<Mass> massList)
    {
       NodeList children = wallXMLElement.getChildNodes();

        for(int i=0; i<children.getLength(); i++)
        {
            Node node = children.item(i);
            if (node instanceof Element)
            {
                Element elem = (Element)node;
                if (elem.getTagName().equals("mass1"))
                {
                    Text textNode = (Text) elem.getFirstChild();
                    String text = textNode.getData().trim();
                    int mass1Index = Integer.parseInt(text);
                    this.m1 = massList.get(mass1Index);
                }
                else if (elem.getTagName().equals("mass2"))
                {
                    Text textNode = (Text) elem.getFirstChild();
                    String text = textNode.getData().trim();
                    int mass1Index = Integer.parseInt(text);
                    this.m2 = massList.get(mass1Index);
                }
            }
        }
    }
    
    public void setPrevNeighbour(Wall w2d)
    {
        prev = w2d;
    }
    public void setNextNeighbour(Wall w2d)
    {
        next = w2d;
    }
    public Wall getPrevNeighbour()
    {
        return prev;
    }
    public Wall getNextNeighbour()
    {
        return next;
    }

    public void setM1(Mass v1) {
        this.m1 = v1;
    }

    public void setM2(Mass v2) {
        this.m2 = v2;
    }
    
    public Mass getM1()
    {
        return m1;
    }
    public Mass getM2()
    {
        return m2;
    }
    public double getVx()
    {
        return m2.getPosition().getX() - m1.getPosition().getX();
    }
    public double getVy()
    {
        return m2.getPosition().getY() - m1.getPosition().getY();
    }
    public Vec2d getVector()
    {
        return new Vec2d( getVx(), getVy() );
    }
    public Vec2d getNormal()
    {
        return getVector().getPerp().getNormalized();
    }
    
    public Rect2d getCatchArea(double catchAreaScale)
    {
        double x = this.m1.getPosition().getX() + (this.m2.getPosition().getX() - this.m1.getPosition().getX())/2;
        double y = this.m1.getPosition().getY() + (this.m2.getPosition().getY() - this.m1.getPosition().getY())/2;
        return new Rect2d( x - WALL2D_CATCH_AREA_SIZE/catchAreaScale, y - WALL2D_CATCH_AREA_SIZE/catchAreaScale,
                           x + WALL2D_CATCH_AREA_SIZE/catchAreaScale, y + WALL2D_CATCH_AREA_SIZE/catchAreaScale );
    }
    public Vec2d getCenter()
    {
        double x = this.m1.getPosition().getX() + (this.m2.getPosition().getX() - this.m1.getPosition().getX())/2;
        double y = this.m1.getPosition().getY() + (this.m2.getPosition().getY() - this.m1.getPosition().getY())/2;

        return new Vec2d(x, y);
    }
    public Sec2d getSector()
    {
        return new Sec2d(getM1().getPosition(), getM2().getPosition());
    }
    public boolean intersectsWith(Sec2d sec)
    {
        if ( getSector().getIntersectionInfo(sec) != null)
            return true;

        return false;
    }
    public void invert()
    {
        Mass tmp = m1;
        m1 = m2;
        m2 = tmp;
    }

    public double getDistTo(Vec2d vec)
    {
        Vec2d v1Tovec = new Vec2d( m1.getPosition() );
        v1Tovec.sub( vec );

        return getNormal().getNormalized().dot( v1Tovec );
    }
    
    public String toString()
    {
        return "Wall2d_"+mid;
    }

    public Element getXMLRepresentation(Document doc, SpringBody sb)
    {
        Element rootElement = doc.createElement("wall");
        rootElement.setAttribute("n", ""+sb.getBorder().getWallList().indexOf(this));

        // Mass 1
        Element mass1Element = doc.createElement("mass1");
        mass1Element.appendChild( doc.createTextNode(""+sb.getMassList().indexOf(m1)) );
        rootElement.appendChild(mass1Element);

        // Mass 2
        Element mass2Element = doc.createElement("mass2");
        mass2Element.appendChild( doc.createTextNode(""+sb.getMassList().indexOf(m2)) );
        rootElement.appendChild(mass2Element);

        return rootElement;
    }

    ////////////////////////////////////////////////////////////////////////////
    //                S C E N E   T R E E   I N T E R F A C E                 //
    ////////////////////////////////////////////////////////////////////////////

    public SceneTreeNode getChild(int index) {
        switch (index) {
            case 0 : return m1;
            case 1 : return m2;
        }

        return null;
    }

    public int getChildCount() {
        return 2;
    }

    public boolean isLeaf() {
        return false;
    }

    public int getIndexOfChild(Object child) {
        if       (child instanceof Mass && child.equals(m1)) return 0;
        else if  (child instanceof Mass && child.equals(m2)) return 1;
        else
            return -1;
    }

    public void resetNodeValue(Object o) {}
}
